{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 本节演示如和更加自由的对模型的参数进行初始化和读取"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "from torch import nn"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "net = nn.Sequential(nn.Linear(4,2),nn.ReLU(),nn.Linear(2,1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 查看参数列表\n",
    "net[0].state_dict()\n",
    "net.state_dict()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 如果是复杂的块呢？\n",
    "seq1 = net\n",
    "def block1():\n",
    "    return nn.Sequential(nn.Linear(1,2),nn.ReLU(),\n",
    "                         nn.Linear(2,1),nn.ReLU())\n",
    "\n",
    "def block2():\n",
    "    net = nn.Sequential()\n",
    "    for i in range(3):\n",
    "        net.add_module(f\"block{i+1}\",block1())\n",
    "    return net\n",
    "\n",
    "net1 = nn.Sequential(block1(),block2(),nn.Linear(1,3))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(net1) # 可以按层访问\n",
    "net1[1][1][0].weight"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "OrderedDict([('0.weight',\n",
       "              tensor([[42.,  2.,  2.,  2.],\n",
       "                      [ 2.,  2.,  2.,  2.]])),\n",
       "             ('0.bias', tensor([ 0.2764, -0.4558])),\n",
       "             ('2.weight', tensor([[42.,  2.]])),\n",
       "             ('2.bias', tensor([0.6925]))])"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 参数初始化\n",
    "def weight_set1(m):\n",
    "    if type(m) == torch.nn.Linear:\n",
    "        # nn.init.ones_(m.weight)\n",
    "        # 初始化为指定的常数\n",
    "        nn.init.constant_(m.weight,2)\n",
    "        # 直接设置参数\n",
    "        m.weight.data[0][0]=42\n",
    "\n",
    "net.apply(weight_set1)\n",
    "net.state_dict()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[True, True, True],\n",
      "        [True, True, True],\n",
      "        [True, True, True],\n",
      "        [True, True, True],\n",
      "        [True, True, True]])\n"
     ]
    }
   ],
   "source": [
    "shared = nn.Linear(3,5)\n",
    "# 其中的两个shared是同一个对象\n",
    "net2 = nn.Sequential(shared,nn.ReLU(),nn.Linear(5,3),shared)\n",
    "print(net2[0].weight == net2[3].weight)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sequential(\n",
      "  (0): Linear(in_features=10, out_features=256, bias=True)\n",
      "  (1): ReLU()\n",
      "  (2): Linear(in_features=256, out_features=10, bias=True)\n",
      ")\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "c:\\Users\\Administrator\\anaconda3\\Lib\\site-packages\\torch\\nn\\modules\\lazy.py:181: UserWarning: Lazy modules are a new feature under heavy development so changes to the API or functionality can happen at any moment.\n",
      "  warnings.warn('Lazy modules are a new feature under heavy development '\n"
     ]
    }
   ],
   "source": [
    "# 延迟初始化\n",
    "lazynet = nn.Sequential(nn.LazyLinear(256),nn.ReLU(),nn.Linear(256,10))\n",
    "x = torch.tensor([1,2,3,4,5,6,7,8,9,0],dtype=torch.float32)\n",
    "lazynet(x)\n",
    "print(lazynet)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 可以保存张量和模型参数\n",
    "torch.save(lazynet.state_dict(),\"test\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([True, True, True, True, True, True, True, True, True, True])\n"
     ]
    }
   ],
   "source": [
    "# 读取\n",
    "clone = lazynet\n",
    "clone.load_state_dict(torch.load(\"test\"))\n",
    "print(clone(x)==lazynet(x))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "base",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
